package com.zhu.ecology;

import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by DELL on 2016/1/30.
 */
public class Sign extends SignAbstruct{
    public static final String TYPE_OF_WEEK = "week";
    public static final String TYPE_OF_MONTH = "month";
    private static final String HOST = "120.27.154.118";
    public static final String SIGN_IN = "1";
    public static final String SIGN_UP = "2";
    private static final String TIME_PATTERN = ".*<td valign=\"top\">[^：]+：([^&]+)&nbsp.*";
    private static final String TABLE_STRING_REGEX = ".*/weaver/weaver.common.util.taglib.SplitPageXmlServlet',0,'','([^']+)'.*";
    private static final String SIGN_IN_DATE_REGEX = ".*column=\"signDate\" orderkey=\"signDate\" linkvalue=\"([^\"]+).*";
    private static final String SIGN_IN_TIME_REGEX = ".*column=\"signTime\" orderkey=\"signTime\" linkvalue=\"([^\"]+).*";
    private static final String SIGN_IN_IP_REGEX = ".*column=\"clientAddress\" orderkey=\"clientAddress\" linkvalue=\"([^\"]+).*";
    private static final String USER_NAME_REGEX = ".*<div title=\"([^\"]+)\" class=\"hrminfo_fontcolor leftColor.*";
    private static final String TIME_FORMAT = "yyy-MM-dd";
    private static final DateFormat DF = new SimpleDateFormat(TIME_FORMAT);

    private String host;
    private HttpClient httpClient;
    boolean isLogined = false;

    public Sign(String name, String password){
        this(HOST, name, password);
    }

    public Sign(String host, String name, String password){
        this.host = host;
        this.username = name;
        this.password = password;
    }

    public void setUserName(String userName){
        this.username = userName;
    }

    public void setPassword(String pwd){
        this.password =pwd;
    }

    public void init(){
        if(httpClient == null) {
            httpClient =new HttpClient();

            List<Header> headers = new ArrayList<Header>();
            headers.add(new Header("User-Agent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)"));
            httpClient.getHostConfiguration().getParams().setParameter("http.default-headers", headers);
        }
    }

    public String signIn(){
        return signIn(SIGN_IN);
    }

    public String signUp(){
        return signIn(SIGN_UP);
    }

    private String signIn(String signType){
        String result = Sign.SIGN_IN.equals(signType)? getSignInTimeOfToday() : null;
        if(result != null){
            return result;
        }

        try {
            if(HttpStatus.SC_OK == login()){
                PostMethod signMethod = new PostMethod("http://" +HOST + ":8080/hrm/schedule/HrmScheduleSignXMLHTTP.jsp?t=0.2532089257147163");
                signMethod.addParameter("signType", signType);

                if(HttpStatus.SC_OK == httpClient.executeMethod(signMethod)){
                    result = subStringWithRegex(signMethod.getResponseBodyAsString(), TIME_PATTERN);
                    if(result != null){
                        if(Sign.SIGN_IN.equals(signType)){
                            LogWriter.writeLog("-----------" +(new SimpleDateFormat(TIME_FORMAT).format(new Date())) + "-----------");
                        }

                        String log = Sign.SIGN_IN.equals(signType)? "签到时间：": "签退时间：";
                        log += result;
                        LogWriter.writeLog(log);
                    }
                }else{
                    result = "failed";
                }
            }else{
                result = "failed";
            }
        }catch(Exception e){
            e.printStackTrace();
        }

        return result;
    }

    private int login() throws IOException {
        int loginResultCode = HttpStatus.SC_OK;
        if(isLogined){
            return loginResultCode;
        }

        init();

        PostMethod loginMethod = new PostMethod("http://" +HOST + ":8080/login/VerifyLogin.jsp");
        loginMethod.setRequestHeader(new Header(
                "User-Agent",
                "Mozilla/5.0 /Windows; U; Windows NT 4.1; de; rv:1.9.1.5) Gecko/20091102 Firefox/3.0"));
        loginMethod.addParameter("loginfile", "/wui/theme/ecology8/page/login.jsp?templateId=4&logintype=1&gopage=");
        loginMethod.addParameter("logintype", "1");
        loginMethod.addParameter("formmethod", "post");
        loginMethod.addParameter("isie", "false");
        loginMethod.addParameter("loginid", username);
        loginMethod.addParameter("userpassword", password);

        loginResultCode = httpClient.executeMethod(loginMethod);
        if(HttpStatus.SC_OK == loginResultCode){
            isLogined = true;
        }

        return loginResultCode;
    }

    public String getUserName() {
        try {
            // http://120.27.154.118:8080/page/element/contacts/data.jsp?hrm=1&ebaseid=contacts&eid=4&styleid=synergys1&hpid=1&subCompanyId=1
            String resultStr = getResponseOfUrl("http://" + HOST + ":8080/wui/main.jsp?templateId=1");
            return subStringWithRegex(resultStr, USER_NAME_REGEX);
        }catch(IOException e){
            e.printStackTrace();
        }
        return null;
    }

    public String getSignInTimeOfToday(){
        try {
            String dayStr = DF.format(new Date());

            List<String> queryResult = getSignInQueryResult(dayStr, dayStr);
            String time = subStringWithRegex(queryResult.get(0), SIGN_IN_TIME_REGEX);
            if(time != null){
                time += "\t\t|\r\n|\t      签到IP：" + subStringWithRegex(queryResult.get(0), SIGN_IN_IP_REGEX);
            }
            return time;
        }catch(IOException e){
            e.printStackTrace();
        }

        return null;
    }

    public String getSignUpTimeOfToday(){
        try {
            String dayStr = DF.format(new Date());

            List<String> queryResult = getSignOutQueryResult(dayStr, dayStr);
            String time = subStringWithRegex(queryResult.get(0), SIGN_IN_TIME_REGEX);
            if(time != null){
                time += "\t\t|\r\n|\t      签到IP：" + subStringWithRegex(queryResult.get(0), SIGN_IN_IP_REGEX);
            }
            return time;
        }catch(IOException e){
            e.printStackTrace();
        }

        return null;
    }

    public List<DaySign> getSignRecord(String startDate, String endDate){
        List<DaySign> resultList = new ArrayList<DaySign>();

        Map<String, DaySign> mapper = new HashMap<String, DaySign>();
        List<String> inResult = getSignInQueryResult(startDate, endDate);
        if(inResult != null){
            try {
                // 解析签到记录
                for(String result : inResult) {
                    String[] dateArr = subStringArrWithRegex(result, SIGN_IN_DATE_REGEX);
                    if (dateArr != null) {
                        String[] timeArr = subStringArrWithRegex(result, SIGN_IN_TIME_REGEX);
                        String[] ipArr = subStringArrWithRegex(result, SIGN_IN_IP_REGEX);
                        int i = 0;
                        for (String date : dateArr) {
                            DaySign sign = new DaySign();
                            sign.setDate(date);
                            sign.setSignInTime(timeArr[i]);
                            sign.setSignInIp(ipArr[i]);

                            resultList.add(sign);
                            mapper.put(date, sign);

                            i++;
                        }
                    }
                }

                // 解析签退记录
                List<String> queryResult = getSignOutQueryResult(startDate, endDate);
                for (String result : queryResult) {
                    String[] dateArr = subStringArrWithRegex(result, SIGN_IN_DATE_REGEX);
                    if (dateArr != null) {
                        String[] timeArr = subStringArrWithRegex(result, SIGN_IN_TIME_REGEX);
                        String[] ipArr = subStringArrWithRegex(result, SIGN_IN_IP_REGEX);
                        int i = 0;
                        for (String date : dateArr) {
                            DaySign sign = mapper.get(date);
                            sign.setSignOutTime(timeArr[i]);
                            sign.setSignOutIp(ipArr[i]);

                            i++;
                        }
                    }
                }
            }catch(IOException e){
                e.printStackTrace();
            }
        }

        return resultList;
    }

    private List<String> getSignOutQueryResult(String startDate, String endDate){
        return getSignQueryResult(startDate, endDate, "Out");
    }

    private List<String> getSignInQueryResult(String startDate, String endDate){
        return getSignQueryResult(startDate, endDate, "In");
    }

    private List<String> getSignQueryResult(String startDate, String endDate, String type){
        List<String> resultList = new ArrayList<String>();

        try {
            String resopnseStr = getResponseOfUrl("http://" + HOST + ":8080/hrm/report/schedulediff/HrmScheduleDiffSign" + type + "Detail.jsp?fromDate=" + startDate + "&toDate=" + endDate);
            String tableString = subStringWithRegex(resopnseStr, TABLE_STRING_REGEX);
            if (tableString != null) {
                String result = getResponseOfUrl("http://" + HOST + ":8080/weaver/weaver.common.util.taglib.SplitPageXmlServlet?tableString=" + tableString);

                int idx = 1;
                while(result != null && result != "" && !result.startsWith("NoData")){
                    resultList.add(result);

                    idx++;
                    result = getResponseOfUrl("http://" + HOST + ":8080/weaver/weaver.common.util.taglib.SplitPageXmlServlet?tableString=" + tableString + "&pageIndex=" + idx);
                }
            }
        }catch(IOException e){
            e.printStackTrace();
            return null;
        }

        return resultList;
    }

    private String getResponseOfUrl(String url){

        PostMethod signMethod = new PostMethod(url);
        try {
            login();
            if (HttpStatus.SC_OK == httpClient.executeMethod(signMethod)) {
                return signMethod.getResponseBodyAsString();
            }
        }catch(IOException e){
            e.printStackTrace();
        }

        return "";
    }

    private String subStringWithRegex(String str, String pattern) throws IOException{
        if(str == null || "".equals(str)){
            return null;
        }

        Pattern p = Pattern.compile(pattern);

        BufferedReader reader = new BufferedReader(new StringReader(str));
        String line = reader.readLine();
        while((line = reader.readLine()) != null){
            Matcher m = p.matcher(line);
            if (m.matches()) {
                return m.group(1);
            }
        }

        return null;
    }

    private String[] subStringArrWithRegex(String str, String pattern) throws IOException{
        if(str == null || "".equals(str)){
            return null;
        }

        List<String> resultList = new ArrayList<String>();
        Pattern p = Pattern.compile(pattern);

        BufferedReader reader = new BufferedReader(new StringReader(str));
        String line = reader.readLine();
        while((line = reader.readLine()) != null){
            Matcher m = p.matcher(line);
            if (m.matches()) {
                resultList.add(m.group(1));
            }
        }

        return resultList.toArray(new String[resultList.size()]);
    }

    private String getMonday(){
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_YEAR, (cal.get(Calendar.DAY_OF_WEEK) + 5)%7 * -1);
        return DF.format(cal.getTime());
    }

    public List<DaySign> getWeekRecord(){
        String monday = getMonday();
        String now = DF.format(new Date());

        return getSignRecord(monday, now);
    }

    private String getFirstDayOfMonth(){
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.DAY_OF_MONTH, 1);

        return DF.format(cal.getTime());
    }

    public List<DaySign> getMonthRecord(){
        String monday = getFirstDayOfMonth();
        String now = DF.format(new Date());

        return getSignRecord(monday, now);
    }

    public static void main(String[] args){
        Sign s = new Sign("02598", "1111");

        try {
            s.login();
            System.out.println(s.getUserName());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
